#pragma once
#include "basecipher.h"
#include <vector>
using namespace std ;

const int MIBS_BLOCK_SIZE = 64 ;
const int MIBS_ROUND = 32 ;
const int MIBS_SBOX_NUM = 16 ;
const int MIBS_KEY_NIBBLE = 8 ;
const int MIBS_WORD_NUM = 2 ;
const int MIBS_SBOX_SIZE = 4 ;
const int MIBS_INNER_NUM = 16 ;

const nibble MIBS_SBOX[MIBS_SBOX_NUM] = { 4 , 15 , 3 , 8 , 
                                           13 , 10 , 12 , 0 , 
										   11 , 5 , 7 , 14 , 
										   2 , 6 , 1 , 9 } ;
const int MIBS_P[MIBS_KEY_NIBBLE] = { 1 , 7 , 0 , 2 , 5 , 6 , 3 , 4 } ;

class MIBS :
	public BaseCipher
{
public:
	MIBS( const int BlockSize , 
		      const int Round , 
			  const int SboxSize , 
			  const key_t InitialKey , 
			  const plaintext_t Plaintext ,
			  ciphertext_t Ciphertext );
	~MIBS(void);	
	void Encryption() ;
	void Decryption() ;
	void print() ;

private:
	nibble RoundKey[MIBS_ROUND][MIBS_KEY_NIBBLE] ;
	nibble innerstate[MIBS_INNER_NUM] ;
	void mibs_keyxor( nibble in_key[] , nibble roundkey[] , const int array_num , nibble out_key[] ) ;
	void mibs_sbox( nibble in_sbox[] , const int array_num , nibble out_sbox[] ) ;
//	void mibs_xor( nibble in_xor[] , const int array_num , nibble out_xor[] ) ;
	void mibs_p( nibble in_p[] , const int array_num , nibble out_p[] ) ;
	void mibs_mix( nibble in_mix[] , const int array_num , nibble out_mix[] ) ;
	void KeySchedule( key_t InitialKey ) ;
	void OneRound( const int round ) ;
	void InvOneRound() ;
};



